Link to this headingBluetooth CTF

Link to this headingScripts

detection_callback.py:

import argparse import asyncio import logging from bleak import BleakScanner from bleak.backends.device import BLEDevice from bleak.backends.scanner import AdvertisementData logger = logging.getLogger(__name__) printed_devices = {} def simple_callback(device: BLEDevice, advertisement_data: AdvertisementData): if device.address not in printed_devices: printed_devices[device.address] = advertisement_data logger.info("{}: {}".format(device.address, advertisement_data)) async def main(args: argparse.Namespace): scanner = BleakScanner( simple_callback, args.services, cb=dict(use_bdaddr=args.macos_use_bdaddr) ) while True: #logger.info("(re)starting scanner") await scanner.start() await asyncio.sleep(5.0) await scanner.stop() #Print New BLE Devices if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--macos-use-bdaddr", action="store_true", help="when true use Bluetooth address instead of UUID on macOS", ) parser.add_argument( "--services", metavar="<uuid>", nargs="*", help="UUIDs of one or more services to filter for", ) parser.add_argument( "-d", "--debug", action="store_true", help="sets the logging level to debug", ) args = parser.parse_args() log_level = logging.DEBUG if args.debug else logging.INFO logging.basicConfig( level=log_level, format="%(asctime)-15s %(name)-8s %(levelname)s: %(message)s", ) asyncio.run(main(args))

service_explorer.py

import argparse import asyncio import logging import collections from bleak import BleakClient, BleakScanner logger = logging.getLogger(__name__) async def main(args: argparse.Namespace): output = {} logger.info("starting scan...") if args.address: device = await BleakScanner.find_device_by_address( args.address, cb=dict(use_bdaddr=args.macos_use_bdaddr) ) if device is None: logger.error("could not find device with address '%s'", args.address) return else: device = await BleakScanner.find_device_by_name( args.name, cb=dict(use_bdaddr=args.macos_use_bdaddr) ) if device is None: logger.error("could not find device with name '%s'", args.name) return logger.info("connecting to device...") async with BleakClient(device, services=args.services) as client: logger.info("connected") for service in client.services: #logger.info("[Service] %s", service) output[service.handle] = {"info": "[Service] {}".format(service)} output[service.handle]["characteristics"] = {} for char in service.characteristics: if "read" in char.properties: try: value = await client.read_gatt_char(char.uuid) output[service.handle]["characteristics"][char.handle] = {"info": " [Characteristic] {} ({}), Value: {}".format(char, ",".join(char.properties), value)} except Exception as e: output[service.handle]["characteristics"][char.handle] = {"info": " [Characteristic] {} ({}), Error: {}".format(char, ",".join(char.properties), e)} else: output[service.handle]["characteristics"][char.handle] = {"info": " [Characteristic] {} ({})".format(char, ",".join(char.properties))} #init descriptors output[service.handle]["characteristics"][char.handle]["descriptors"] = {} for descriptor in char.descriptors: try: value = await client.read_gatt_descriptor(descriptor.handle) output[service.handle]["characteristics"][char.handle]["descriptors"][descriptor.handle] = {"info": " [Descriptor] {}, Value: {}".format(descriptor, value)} except Exception as e: output[service.handle]["characteristics"][char.handle]["descriptors"][descriptor.handle] = {"info": " [Descriptor] {}, Error: {}".format(descriptor, e)} #Sort Descriptors output[service.handle]["characteristics"][char.handle]["descriptors"] = dict(sorted(output[service.handle]["characteristics"][char.handle]["descriptors"].items())) #Sort Characteristics output[service.handle]["characteristics"] = dict(sorted(output[service.handle]["characteristics"].items())) #Sort Services output = dict(sorted(output.items())) #Print Services for service_handle in output: logger.info(output[service_handle]["info"]) #Print Characteristics for characteristic in output[service_handle]["characteristics"]: logger.info(output[service_handle]["characteristics"][characteristic]["info"]) #Print Descriptors for descriptor in output[service_handle]["characteristics"][characteristic]["descriptors"]: logger.info(output[service_handle]["characteristics"][characteristic]["descriptors"][descriptor]["info"]) logger.info("disconnecting...") logger.info("disconnected") if __name__ == "__main__": parser = argparse.ArgumentParser() device_group = parser.add_mutually_exclusive_group(required=True) device_group.add_argument( "--name", metavar="<name>", help="the name of the bluetooth device to connect to", ) device_group.add_argument( "--address", metavar="<address>", help="the address of the bluetooth device to connect to", ) parser.add_argument( "--macos-use-bdaddr", action="store_true", help="when true use Bluetooth address instead of UUID on macOS", ) parser.add_argument( "--services", nargs="+", metavar="<uuid>", help="if provided, only enumerate matching service(s)", ) parser.add_argument( "-d", "--debug", action="store_true", help="sets the log level to debug", ) args = parser.parse_args() log_level = logging.DEBUG if args.debug else logging.INFO logging.basicConfig( level=log_level, format="%(asctime)-15s %(name)-8s %(levelname)s: %(message)s", ) asyncio.run(main(args))

service_writer.py:

import asyncio, string, platform, sys, argparse from bleak import BleakClient from bleak.uuids import normalize_uuid_16, uuid16_dict async def main(args: argparse.Namespace): async with BleakClient(args.device, winrt=dict(use_cached_services=True)) as client: print(f"Connected: {client.is_connected}") #Read UUID or handle if args.debug: read_data = await client.read_gatt_char(args.service) print(f"Read[{args.service}]: {read_data}") #Write data to UUID or handle print(f"Write[{args.service}]: {args.data}") value = await client.read_gatt_char(args.service) print(f"Returned Data: {value}") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--macos-use-bdaddr", action="store_true", help="when true use Bluetooth address instead of UUID on macOS", ) parser.add_argument( "--device", required=True, help="Which Device MAC to connect to", ) parser.add_argument( "--service", required=True, help="UUID or Handle to write to", ) parser.add_argument( "--data", required=True, help="the Data to write. Can be 0x02, or \"test\"", ) parser.add_argument( "-v", dest="debug", action="store_true", help="sets the logging level to debug", ) args = parser.parse_args() print(args) #Convert to bytes if args.data.starts_with("0x") and all(c in string.hexdigits for c in args.data): args.data = int(args.data, 16) else: args.data = args.data.encode() log_level = logging.DEBUG if args.debug else logging.INFO logging.basicConfig( level=log_level, format="%(asctime)-15s %(name)-8s %(levelname)s: %(message)s", ) asyncio.run(main(args))

Link to this headingSetup

Setup Bluetooth:

yay -S bleah bleak sudo systemctl start bluetooth.service # You might need to edit the service file and add a -E to the end of the ExecStart #ExecStart=/usr/lib/bluetooth/bluetoothd -E

Scanning for Devices:

>>> python detection_callback.py 2023-11-13 22:21:01,667 __main__ INFO: E1:A1:E5:38:52:DD: AdvertisementData(local_name='F48F92878BF433A8EA', manufacturer_data={1447: b'\x05\x10\x01\x00\x00\x00\x00\x00\x00\x04#\x00\xca'}, service_uuids=['0000fe07-0000-1000-8000-00805f9b34fb'], tx_power=0, rssi=-77) 2023-11-13 22:21:01,671 __main__ INFO: 64:E8:33:82:AF:6A: AdvertisementData(local_name='BLECTF', service_uuids=['000000ff-0000-1000-8000-00805f9b34fb'], tx_power=-21, rssi=-33) 2023-11-13 22:21:01,731 __main__ INFO: 5B:40:40:4E:17:66: AdvertisementData(manufacturer_data={76: b'\x07\x19\x01\x14 !2\x8f\x11\x00\x043C\xe1\xee84$#\xa1(\xcb\x94\x81\x8a\x83\x85'}, rssi=-63) 2023-11-13 22:21:01,731 __main__ INFO: D8:EB:80:A5:37:B0: AdvertisementData(manufacturer_data={76: b'\x12\x02\x00\x00'}, rssi=-83) 2023-11-13 22:21:01,742 __main__ INFO: 08:2A:49:00:56:1E: AdvertisementData(manufacturer_data={6: b'\x01\t "\xf5\xb4\x10\xec\xe8\xbc\xeaS7\xe6%\x00,\xe1\x9a\x11E\xa0\xf4\x90#\x07\x1e'}, rssi=-72) 2023-11-13 22:21:01,745 __main__ INFO: 49:03:08:8E:A1:91: AdvertisementData(manufacturer_data={76: b'\x10\x06s\x1de\xccHx'}, tx_power=7, rssi=-78) 2023-11-13 22:21:01,772 __main__ INFO: 64:13:D4:80:A3:4C: AdvertisementData(manufacturer_data={76: b'\x10\x07x\x1fe>G\x16\x80'}, tx_power=7, rssi=-84) 2023-11-13 22:21:01,773 __main__ INFO: 00:4D:32:11:6F:C1: AdvertisementData(local_name='HS2S 11070', manufacturer_data={71: b'\x00\x00\x00\x00\x00M2\x11o\xc1'}, service_uuids=['636f6d2e-6a69-7561-6e2e-424653563232'], tx_power=0, rssi=-80) 2023-11-13 22:21:01,783 __main__ INFO: 71:A5:1D:B5:32:01: AdvertisementData(manufacturer_data={76: b'\x10\x07\x1d\x1b\xb6\xf3\xb0\xc8('}, tx_power=11, rssi=-81) 2023-11-13 22:21:01,815 __main__ INFO: 0A:4A:29:47:E9:FF: AdvertisementData(manufacturer_data={76: b'\t\x06\x03\xb8\xc0\xa8\x01F'}, rssi=-78) 2023-11-13 22:21:01,863 __main__ INFO: 2C:4C:C6:0E:C4:81: AdvertisementData(local_name='Venus_2C4CC60EC481', manufacturer_data={9474: b'\x00\x8c\x00\x00\xc16'}, service_uuids=['06aa1910-f22a-11e3-9daa-0002a5d5c51b'], rssi=-83) 2023-11-13 22:21:01,864 __main__ INFO: C9:01:59:A3:44:2B: AdvertisementData(manufacturer_data={76: b'\x12\x02d\x02\x07\x11\x06\x91\xdb\xb3h\x8eS\xd0.\xbdSU\xba\xa69\x8aG'}, rssi=-75) 2023-11-13 22:21:01,895 __main__ INFO: 57:97:97:9E:7F:9C: AdvertisementData(manufacturer_data={224: b'X\x07\xcas`\x10'}, service_data={'0000fe9f-0000-1000-8000-00805f9b34fb': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'}, service_uuids=['0000fe9f-0000-1000-8000-00805f9b34fb'], rssi=-52) 2023-11-13 22:21:01,936 __main__ INFO: 7E:48:71:E2:7D:73: AdvertisementData(manufacturer_data={76: b'\x10\x06O\x1dFbo\x18'}, tx_power=5, rssi=-82) 2023-11-13 22:21:01,936 __main__ INFO: 5C:C1:D7:72:87:97: AdvertisementData(local_name='[TV] Samsung 7 Series (50)', manufacturer_data={117: b'B\x04\x01\x80f\\\xc1\xd7r\x87\x97^\xc1\xd7r\x87\x96\x01\x00\x00\x00\x00\x00\x00'}, rssi=-78) 2023-11-13 22:21:01,966 __main__ INFO: 7D:09:8F:04:AB:40: AdvertisementData(manufacturer_data={76: b'\x0c\x0e\x00!IU\xfb\x17\xa0\xe4\xd0\x0e\xc7@\t\x19\x10\x06s\x1d\xd0\x9bI('}, rssi=-86) 2023-11-13 22:21:01,966 __main__ INFO: 1C:B3:C9:31:23:8F: AdvertisementData(manufacturer_data={76: b'\x10\x05\x01\x10+\xf0<'}, tx_power=4, rssi=-71) 2023-11-13 22:21:02,271 __main__ INFO: E4:FC:95:73:04:94: AdvertisementData(local_name='Hatch Rest', service_data={'0000180f-0000-1000-8000-00805f9b34fb': b'd'}, service_uuids=['0000180a-0000-1000-8000-00805f9b34fb', '0000180f-0000-1000-8000-00805f9b34fb'], rssi=-83) 2023-11-13 22:21:02,340 __main__ INFO: 0E:8F:3C:F4:EE:31: AdvertisementData(manufacturer_data={76: b'\t\x08\x13\xa0\xc0\xa827\x1bX'}, rssi=-85) 2023-11-13 22:21:02,527 __main__ INFO: 7E:39:F0:B7:2B:4D: AdvertisementData(manufacturer_data={76: b'\x10\x05<\x1c\x80\x15\x0c'}, tx_power=12, rssi=-85) 2023-11-13 22:21:02,946 __main__ INFO: 75:4E:57:6B:5A:DA: AdvertisementData(manufacturer_data={76: b'\x10\x05&\x18\x91\t\x8c'}, tx_power=8, rssi=-80) 2023-11-13 22:21:03,337 __main__ INFO: CB:0B:A7:63:74:BF: AdvertisementData(manufacturer_data={76: b'\x12\x02\x00\x01'}, rssi=-83) 2023-11-13 22:21:03,410 __main__ INFO: 7B:75:51:E5:65:CE: AdvertisementData(manufacturer_data={76: b'\t\x08\x13\x84\xc0\xa8\x00y\x1bX\x13\x07\x02\xf1:\xe6h\xd5\xa7'}, rssi=-88) 2023-11-13 22:21:03,425 __main__ INFO: FA:BA:C9:96:86:5F: AdvertisementData(local_name='98E78202A2C83397E9', manufacturer_data={1447: b'\x05\x10\x01\x00\x00\x00\x00\x00\x00\x02#\x00\xca'}, service_uuids=['0000fe07-0000-1000-8000-00805f9b34fb'], rssi=-84) 2023-11-13 22:21:03,778 __main__ INFO: 72:0D:34:BE:A0:C4: AdvertisementData(manufacturer_data={76: b'\x10\x07z\x1f\xb8\xccG\xfa\x80'}, tx_power=7, rssi=-80) 2023-11-13 22:21:03,778 __main__ INFO: C5:06:F6:45:C4:8B: AdvertisementData(manufacturer_data={76: b'\x12\x02\x00\x00'}, rssi=-82) 2023-11-13 22:21:04,399 __main__ INFO: 7D:38:31:ED:39:43: AdvertisementData(manufacturer_data={76: b'\x10\x06O\x1dFbo\x18'}, tx_power=5, rssi=-82) 2023-11-13 22:21:04,885 __main__ INFO: DE:07:E3:73:56:E2: AdvertisementData(manufacturer_data={76: b'\x12\x02n\x03\x07\x11\x06I\x15\xb67\xd3J^\x99t\xa4\tVyu\xdeV'}, rssi=-78) 2023-11-13 22:21:05,028 __main__ INFO: 57:3F:49:79:A1:CF: AdvertisementData(manufacturer_data={76: b'\t\x08\x13\xa7\xc0\xa8\x01\x0c\x1bX'}, rssi=-83) 2023-11-13 22:21:05,043 __main__ INFO: E7:38:83:A1:46:9D: AdvertisementData(manufacturer_data={76: b'\x12\x02\x00\x03'}, rssi=-79) 2023-11-13 22:21:05,319 __main__ INFO: E3:36:5D:AE:20:D4: AdvertisementData(manufacturer_data={76: b'\x12\x19\x102\x8dM\xdb#d\x0f\xccN\x1d\xb2\xce\x17!l\xdb\xef\xacn\xf6F\xcc\x03\xd4'}, rssi=-76) 2023-11-13 22:21:05,415 __main__ INFO: C7:2D:EA:36:45:B2: AdvertisementData(manufacturer_data={76: b'\x12\x02\xac\x02'}, rssi=-71) 2023-11-13 22:21:05,601 __main__ INFO: C4:57:DC:51:D9:E4: AdvertisementData(manufacturer_data={76: b'\x12\x02\xa5\x03'}, rssi=-63) 2023-11-13 22:21:05,870 __main__ INFO: 52:03:53:87:0B:A2: AdvertisementData(manufacturer_data={76: b'\x10\x05{\x1c\x88\xb8\r'}, tx_power=8, rssi=-85) 2023-11-13 22:21:06,404 __main__ INFO: 44:F2:D3:91:C7:1A: AdvertisementData(service_uuids=['0000180f-0000-1000-8000-00805f9b34fb'], rssi=-83) 2023-11-13 22:21:06,479 __main__ INFO: 4B:BA:AF:E7:1E:21: AdvertisementData(manufacturer_data={76: b'\x10\x06\r\x1d\x8a\xa6\x80\x08'}, tx_power=4, rssi=-88)

List Capabilities (bleah):

>>> sudo bleah -b "64:E8:33:82:AF:6A" -e @ Scanning for 5s [-128 dBm of sensitivity] ... 64:e8:33:82:af:6a (-34 dBm) ──────────────────────────────────────────┐ Vendor │ ? Allows Connections │ ✓ │ Address Type │ public │ Tx Power │ u'eb' Complete 16b Services │ '000000ff-0000-1000-8000-00805f9b34fb' Complete Local Name │ BLECTF │ Flags │ LE General Discoverable, BR/EDR Not Supported │ └───────────────────────┴───────────────────────────────────────────────┘ @ Connecting to 64:e8:33:82:af:6a ... connected. @ Enumerating all the things ... ┌──────────────┬────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────┐ Handles │ Service > Characteristics │ Properties │ Data │ ├──────────────┼────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────┤ 0001 -> 000b │ Generic Attribute ( 00001801-0000-1000-8000-00805f9b34fb ) │ │ 0003 │ Service Changed ( 00002a05-0000-1000-8000-00805f9b34fb ) INDICATE │ │ 0006 │ 2b29 ( 00002b29-0000-1000-8000-00805f9b34fb ) READ WRITE │ '\x04' 0008 │ 2b2a ( 00002b2a-0000-1000-8000-00805f9b34fb ) READ │ '\xe5\xc2\xaa\x8b\xb1!\xce\xaf\xef\xe3\xb9\xf3\xd5\xa3\xc21' 000a │ 2b3a ( 00002b3a-0000-1000-8000-00805f9b34fb ) READ │ '\x00' │ │ │ │ 0014 -> 001c │ Generic Access ( 00001800-0000-1000-8000-00805f9b34fb ) │ │ 0016 │ Device Name ( 00002a00-0000-1000-8000-00805f9b34fb ) READ │ u'2b00042f7481c7b056c4b410d28f33cf' 0018 │ Appearance ( 00002a01-0000-1000-8000-00805f9b34fb ) READ │ Unknown │ 001a │ Central Address Resolution ( 00002aa6-0000-1000-8000-00805f9b34fb ) READ │ '\x00' │ │ │ │ 0028 -> ffff │ 00ff ( 000000ff-0000-1000-8000-00805f9b34fb ) │ │ 002a │ ff01 ( 0000ff01-0000-1000-8000-00805f9b34fb ) READ │ u'Score: 0/20' 002c │ ff02 ( 0000ff02-0000-1000-8000-00805f9b34fb ) READ WRITE │ u'Write Flags Here' 002e │ ff03 ( 0000ff03-0000-1000-8000-00805f9b34fb ) READ │ u'd205303e099ceff44835' 0030 │ ff04 ( 0000ff04-0000-1000-8000-00805f9b34fb ) READ │ u'MD5 of Device Name' 0032 │ ff05 ( 0000ff05-0000-1000-8000-00805f9b34fb ) READ WRITE │ u'Write anything here' 0034 │ ff06 ( 0000ff06-0000-1000-8000-00805f9b34fb ) READ WRITE │ u'Write the ascii value "yo" here' 0036 │ ff07 ( 0000ff07-0000-1000-8000-00805f9b34fb ) READ WRITE │ u'Write the hex value 0x07 here' 0038 │ ff08 ( 0000ff08-0000-1000-8000-00805f9b34fb ) READ │ u'Write 0xC9 to handle 58' 003a │ ff09 ( 0000ff09-0000-1000-8000-00805f9b34fb ) WRITE │ │ 003c │ ff0a ( 0000ff0a-0000-1000-8000-00805f9b34fb ) READ WRITE │ u'Brute force my value 00 to ff' 003e │ ff0b ( 0000ff0b-0000-1000-8000-00805f9b34fb ) READ │ u'Read me 1000 times' 0040 │ ff0c ( 0000ff0c-0000-1000-8000-00805f9b34fb ) NOTIFY READ WRITE │ u'Listen to me for a single notification' 0042 │ ff0d ( 0000ff0d-0000-1000-8000-00805f9b34fb ) READ │ u'Listen to handle 0x0044 for a single indication' 0044 │ ff0e ( 0000ff0e-0000-1000-8000-00805f9b34fb ) READ INDICATE WRITE │ │ 0046 │ ff0f ( 0000ff0f-0000-1000-8000-00805f9b34fb ) NOTIFY READ WRITE │ u'Listen to me for multi notifications' 0048 │ ff10 ( 0000ff10-0000-1000-8000-00805f9b34fb ) READ │ u'Listen to handle 0x004a for multi indications' 004a │ ff11 ( 0000ff11-0000-1000-8000-00805f9b34fb ) READ INDICATE WRITE │ │ 004c │ ff12 ( 0000ff12-0000-1000-8000-00805f9b34fb ) READ │ u'Connect with BT MAC address 11:22:33:44:55:66' 004e │ ff13 ( 0000ff13-0000-1000-8000-00805f9b34fb ) READ │ u'Set your connection MTU to 444' 0050 │ ff14 ( 0000ff14-0000-1000-8000-00805f9b34fb ) READ WRITE │ u"Write+resp 'hello' " 0052 │ ff15 ( 0000ff15-0000-1000-8000-00805f9b34fb ) READ WRITE │ u'No notifications here! really?' 0054 │ ff16 ( 0000ff16-0000-1000-8000-00805f9b34fb ) NOTIFY BROADCAST READ WRITE EXTENDED PROPERTIES │ u'So many properties!' 0056 │ ff17 ( 0000ff17-0000-1000-8000-00805f9b34fb ) READ │ u"md5 of author's twitter handle" │ │ │ │ └──────────────┴────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────┘ ()

List Capabilities Python:

>>> python service_explorer.py --name BLECTF 2023-11-13 22:55:50,730 __main__ INFO: starting scan... 2023-11-13 22:55:50,861 __main__ INFO: connecting to device... 2023-11-13 22:55:52,262 __main__ INFO: connected 2023-11-13 22:55:54,629 __main__ INFO: [Service] 00001801-0000-1000-8000-00805f9b34fb (Handle: 1): Generic Attribute Profile 2023-11-13 22:55:54,629 __main__ INFO: [Characteristic] 00002a05-0000-1000-8000-00805f9b34fb (Handle: 2): Service Changed (indicate) 2023-11-13 22:55:54,629 __main__ INFO: [Descriptor] 00002902-0000-1000-8000-00805f9b34fb (Handle: 4): Client Characteristic Configuration, Value: bytearray(b'\x02\x00') 2023-11-13 22:55:54,629 __main__ INFO: [Characteristic] 00002b29-0000-1000-8000-00805f9b34fb (Handle: 5): Client Supported Features (read,write), Value: bytearray(b'\x05') 2023-11-13 22:55:54,629 __main__ INFO: [Characteristic] 00002b2a-0000-1000-8000-00805f9b34fb (Handle: 7): Database Hash (read), Value: bytearray(b'\xe5\xc2\xaa\x8b\xb1!\xce\xaf\xef\xe3\xb9\xf3\xd5\xa3\xc21') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 00002b3a-0000-1000-8000-00805f9b34fb (Handle: 9): Server Supported Features (read), Value: bytearray(b'\x00') 2023-11-13 22:55:54,630 __main__ INFO: [Service] 000000ff-0000-1000-8000-00805f9b34fb (Handle: 40): Vendor specific 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:8 /20') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff02-0000-1000-8000-00805f9b34fb (Handle: 43): Vendor specific (read,write), Value: bytearray(b'Write Flags Here') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff03-0000-1000-8000-00805f9b34fb (Handle: 45): Vendor specific (read), Value: bytearray(b'd205303e099ceff44835') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff04-0000-1000-8000-00805f9b34fb (Handle: 47): Vendor specific (read), Value: bytearray(b'MD5 of Device Name') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff05-0000-1000-8000-00805f9b34fb (Handle: 49): Vendor specific (read,write), Value: bytearray(b'3873c0270763568cf7aa') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff06-0000-1000-8000-00805f9b34fb (Handle: 51): Vendor specific (read,write), Value: bytearray(b'c55c6314b3db0a6128af') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff07-0000-1000-8000-00805f9b34fb (Handle: 53): Vendor specific (read,write), Value: bytearray(b'1179080b29f8da16ad66') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff08-0000-1000-8000-00805f9b34fb (Handle: 55): Vendor specific (read), Value: bytearray(b'f8b136d937fad6a2be9f') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff09-0000-1000-8000-00805f9b34fb (Handle: 57): Vendor specific (write) 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff0a-0000-1000-8000-00805f9b34fb (Handle: 59): Vendor specific (read,write), Value: bytearray(b'Brute force my value 00 to ff') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff0b-0000-1000-8000-00805f9b34fb (Handle: 61): Vendor specific (read), Value: bytearray(b'Read me 1000 times') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff0c-0000-1000-8000-00805f9b34fb (Handle: 63): Vendor specific (read,write,notify), Value: bytearray(b'Listen to me for a single notification') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff0d-0000-1000-8000-00805f9b34fb (Handle: 65): Vendor specific (read), Value: bytearray(b'Listen to handle 0x0044 for a single indication') 2023-11-13 22:55:54,630 __main__ INFO: [Characteristic] 0000ff0e-0000-1000-8000-00805f9b34fb (Handle: 67): Vendor specific (read,write,indicate), Value: bytearray(b'Listen to handle 0x0044 for a single indication\x00') 2023-11-13 22:55:54,631 __main__ INFO: [Characteristic] 0000ff0f-0000-1000-8000-00805f9b34fb (Handle: 69): Vendor specific (read,write,notify), Value: bytearray(b'Listen to me for multi notifications') 2023-11-13 22:55:54,631 __main__ INFO: [Characteristic] 0000ff10-0000-1000-8000-00805f9b34fb (Handle: 71): Vendor specific (read), Value: bytearray(b'Listen to handle 0x004a for multi indications') 2023-11-13 22:55:54,631 __main__ INFO: [Characteristic] 0000ff11-0000-1000-8000-00805f9b34fb (Handle: 73): Vendor specific (read,write,indicate), Value: bytearray(b'Listen to handle 0x004a for multi indications\x00') 2023-11-13 22:55:54,631 __main__ INFO: [Characteristic] 0000ff12-0000-1000-8000-00805f9b34fb (Handle: 75): Vendor specific (read), Value: bytearray(b'Connect with BT MAC address 11:22:33:44:55:66') 2023-11-13 22:55:54,631 __main__ INFO: [Characteristic] 0000ff13-0000-1000-8000-00805f9b34fb (Handle: 77): Vendor specific (read), Value: bytearray(b'Set your connection MTU to 444') 2023-11-13 22:55:54,631 __main__ INFO: [Characteristic] 0000ff14-0000-1000-8000-00805f9b34fb (Handle: 79): Vendor specific (read,write), Value: bytearray(b"Write+resp \'hello\' ") 2023-11-13 22:55:54,631 __main__ INFO: [Characteristic] 0000ff15-0000-1000-8000-00805f9b34fb (Handle: 81): Vendor specific (read,write), Value: bytearray(b'No notifications here! really?') 2023-11-13 22:55:54,631 __main__ INFO: [Characteristic] 0000ff16-0000-1000-8000-00805f9b34fb (Handle: 83): Vendor specific (broadcast,read,write,notify,extended-properties), Value: bytearray(b'So many properties!') 2023-11-13 22:55:54,631 __main__ INFO: [Characteristic] 0000ff17-0000-1000-8000-00805f9b34fb (Handle: 85): Vendor specific (read), Value: bytearray(b"md5 of author\'s twitter handle") 2023-11-13 22:55:54,631 __main__ INFO: disconnecting... 2023-11-13 22:55:56,665 __main__ INFO: disconnected

Link to this headingCommon Functions

Read Values (bluetoothctl):

>>> bluetoothctl hci0 new_settings: powered bondable ssp br/edr le secure-conn Agent registered [CHG] Controller A8:7E:EA:C2:EB:46 Pairable: yes [2b00042f7481c7b056c4b410d28f33cf]# menu gatt [2b00042f7481c7b056c4b410d28f33cf]# select-attribute 0000ff01-0000-1000-8000-00805f9b34fb [2b00042f7481c7b056c4b410d28f33cf:/service0028/char0029]# read Attempting to read /org/bluez/hci0/dev_64_E8_33_82_AF_6A/service0028/char0029 [CHG] Attribute /org/bluez/hci0/dev_64_E8_33_82_AF_6A/service0028/char0029 Value: 53 63 6f 72 65 3a 20 30 2f 32 30 Score: 0/20 53 63 6f 72 65 3a 20 30 2f 32 30 Score: 0/20

Read Values (python):

>>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep 0000ff01-0000-1000-8000-00805f9b34fb 2023-11-13 23:00:37,073 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:8 /20')

Write Values (python):

Write Values (bleah):

sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff02-0000-1000-8000-00805f9b34fb -d "5cd56d74049ae40f442ece036c6f4f06" sudo bleah -b "64:E8:33:82:AF:6A" -n 0x002c -d "5cd56d74049ae40f442ece036c6f4f06" sudo bleah -b "64:E8:33:82:AF:6A" -n 43 -d "5cd56d74049ae40f442ece036c6f4f06"

Write Values (bluetoothctl):

#Dosent work

Link to this headingFlag 1

Write a Flag:

>>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff02-0000-1000-8000-00805f9b34fb -d "12345678901234567890" @ Scanning for 5s [-128 dBm of sensitivity] ... 64:e8:33:82:af:6a (-37 dBm) ──────────────────────────────────────────┐ Vendor │ ? Allows Connections │ ✓ │ Address Type │ public │ Tx Power │ u'eb' Complete 16b Services │ '000000ff-0000-1000-8000-00805f9b34fb' Complete Local Name │ BLECTF │ Flags │ LE General Discoverable, BR/EDR Not Supported │ └───────────────────────┴───────────────────────────────────────────────┘ @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff02-0000-1000-8000-00805f9b34fb) ... found @ Sending 20 bytes ... done () ()

Link to this headingFlag 2

Read the Flag with bluetoothctl:

>>> bluetoothctl scan on [2b00042f7481c7b056c4b410d28f33cf]# menu gatt [2b00042f7481c7b056c4b410d28f33cf]# select-attribute 0000ff03-0000-1000-8000-00805f9b34fb [2b00042f7481c7b056c4b410d28f33cf:/service0028/char0029]# read Attempting to read /org/bluez/hci0/dev_64_E8_33_82_AF_6A/service0028/char0029 [CHG] Attribute /org/bluez/hci0/dev_64_E8_33_82_AF_6A/service0028/char0029 Value: 53 63 6f 72 65 3a 20 30 2f 32 30 Score: 0/20 53 63 6f 72 65 3a 20 30 2f 32 30 Score: 0/20

NOTE: Cant write with bluetoothctl

Write a Flag with bluetoothctl:

sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff02-0000-1000-8000-00805f9b34fb -d "d205303e099ceff44835"

Link to this headingFlag 3

#md5("BLECTF") = 5cd56d74049ae40f442ece036c6f4f06 >>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff02-0000-1000-8000-00805f9b34fb -d "5cd56d74049ae40f442ece036c6f4f06" [...] @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff02-0000-1000-8000-00805f9b34fb) ... found @ Sending 32 bytes ... done () ()
#Actually wants the first 20 characters >>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff02-0000-1000-8000-00805f9b34fb -d "5cd56d74049ae40f442e"

Link to this headingFlag 4

Get device name and sent it to 0000ff02-0000-1000-8000-00805f9b34fb.

[BLECTF]# info Device 64:E8:33:82:AF:6A (public) Name: 2b00042f7481c7b056c4b410d28f33cf Alias: 2b00042f7481c7b056c4b410d28f33cf Paired: no Bonded: no Trusted: no Blocked: no Connected: yes LegacyPairing: no UUID: Unknown (000000ff-0000-1000-8000-00805f9b34fb) UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb) UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb) AdvertisingFlags: 06
>>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff02-0000-1000-8000-00805f9b34fb -d "2b00042f7481c7b056c4" @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff02-0000-1000-8000-00805f9b34fb) ... found @ Sending 20 bytes ... done () ()

Link to this headingFlag 5

Write anything to 0000ff05-0000-1000-8000-00805f9b34fb

>>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff05-0000-1000-8000-00805f9b34fb -d "anything" @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff02-0000-1000-8000-00805f9b34fb) ... found @ Sending 20 bytes ... done () ()

After anything is written the data is changed

[BLECTF]# select-attribute 0000ff05-0000-1000-8000-00805f9b34fb [2b00042f7481c7b056c4b410d28f33cf:/service0028/char0031]# read Attempting to read /org/bluez/hci0/dev_64_E8_33_82_AF_6A/service0028/char0031 [CHG] Attribute /org/bluez/hci0/dev_64_E8_33_82_AF_6A/service0028/char0031 Value: 33 38 37 33 63 30 32 37 30 37 36 33 35 36 38 63 3873c0270763568c 66 37 61 61 f7aa 33 38 37 33 63 30 32 37 30 37 36 33 35 36 38 63 3873c0270763568c 66 37 61 61 f7aa [2b00042f7481c7b056c4b410d28f33cf:/service0028/char0031]#

Write the flag

>>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff02-0000-1000-8000-00805f9b34fb -d "3873c0270763568cf7aa" [...] @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff02-0000-1000-8000-00805f9b34fb) ... found @ Sending 20 bytes ... done () ()

Link to this headingFlag 6

Write ascii “yo”

>>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff06-0000-1000-8000-00805f9b34fb -d "yo" [...] @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff06-0000-1000-8000-00805f9b34fb) ... found @ Sending 2 bytes ... done () ()

Read the flag from the 0000ff06-0000-1000-8000-00805f9b34fb handle

Write the flag

>>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff02-0000-1000-8000-00805f9b34fb -d "c55c6314b3db0a6128af" [...] @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff02-0000-1000-8000-00805f9b34fb) ... found @ Sending 20 bytes ... done () ()

Link to this headingFlag 7

Write binary 0x07

>>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff07-0000-1000-8000-00805f9b34fb -d 0x07 [...] @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff07-0000-1000-8000-00805f9b34fb) ... found @ Sending 1 bytes ... done () ()

Read the flag from the 0000ff07-0000-1000-8000-00805f9b34fb handle

Write the flag

>>> sudo bleah -b "64:E8:33:82:AF:6A" -u 0000ff02-0000-1000-8000-00805f9b34fb -d "1179080b29f8da16ad66" [...] @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff02-0000-1000-8000-00805f9b34fb) ... found @ Sending 20 bytes ... done () ()

Link to this headingFlag 8

Write 0xC9 to handle 58. 58 == 0x003a

sudo bleah -b "64:E8:33:82:AF:6A" -n 0x003a -d 0xC9 [...] @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic handle(58) ... found @ Sending 1 bytes ... done () ()

Read the flag from the 0000ff08-0000-1000-8000-00805f9b34fb handle

Write the flag

>>> sudo bleah -b "64:E8:33:82:AF:6A" -n 0x002a -d "f8b136d937fad6a2be9f" [...] @ Connecting to 64:e8:33:82:af:6a ... connected. () @ Searching for characteristic uuid(0000ff02-0000-1000-8000-00805f9b34fb) ... found @ Sending 20 bytes ... done () ()

Link to this headingFlag 9

Modified write Script

import asyncio, string, platform, sys, argparse, logging from bleak import BleakClient from bleak.uuids import normalize_uuid_16, uuid16_dict logger = logging.getLogger(__name__) async def flag9(args: argparse.Namespace): async with BleakClient(args.device, winrt=dict(use_cached_services=True)) as client: logger.info(f"Connected: {client.is_connected}") for i in range(255): write_data = bytearray([i]) #Read UUID or handle read_data = await client.read_gatt_char(args.service) logger.info(f"Read[{args.service}]: {read_data}") #Write data to UUID or handle logger.info(f"Write[{args.service}]: {write_data}") value = await client.write_gatt_char(args.service, write_data, response=True) logger.info(f"Returned Data: {value}") async def main(args: argparse.Namespace): async with BleakClient(args.device, winrt=dict(use_cached_services=True)) as client: logger.info(f"Connected: {client.is_connected}") #Read UUID or handle read_data = await client.read_gatt_char(args.service) logger.info(f"Read[{args.service}]: {read_data}") #Write data to UUID or handle logger.info(f"Write[{args.service}]: {args.data}") value = await client.write_gatt_char(args.service, args.data, response=True) logger.info(f"Returned Data: {value}") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--macos-use-bdaddr", action="store_true", help="when true use Bluetooth address instead of UUID on macOS", ) parser.add_argument( "--device", required=True, help="Which Device MAC to connect to", ) parser.add_argument( "--service", required=True, help="UUID or Handle to write to", ) parser.add_argument( "--data", required=True, help="the Data to write. Can be 0x02, or \"test\"", ) parser.add_argument( "-v", dest="debug", #default=True, action="store_true", help="sets the logging level to debug", ) args = parser.parse_args() #Convert to bytes if args.data.startswith("0x") and all(c in string.hexdigits for c in args.data): args.data = int(args.data, 16) else: args.data = args.data.encode() log_level = logging.DEBUG if args.debug else logging.INFO logging.basicConfig( level=log_level, format="%(asctime)-15s %(name)-8s %(levelname)s: %(message)s", ) #asyncio.run(main(args)) asyncio.run(flag9(args))

Run the script:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff0a-0000-1000-8000-00805f9b34fb --data 0x00 2023-11-13 23:14:19,135 __main__ INFO: Connected: True 2023-11-13 23:14:19,529 __main__ INFO: Read[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'933c1fcfa8ed52d2ec05') 2023-11-13 23:14:19,529 __main__ INFO: Write[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'\x00') 2023-11-13 23:14:19,608 __main__ INFO: Returned Data: None 2023-11-13 23:14:19,689 __main__ INFO: Read[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'933c1fcfa8ed52d2ec05') 2023-11-13 23:14:19,689 __main__ INFO: Write[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'\x01') 2023-11-13 23:14:19,768 __main__ INFO: Returned Data: None 2023-11-13 23:14:19,849 __main__ INFO: Read[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'933c1fcfa8ed52d2ec05') 2023-11-13 23:14:19,849 __main__ INFO: Write[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'\x02') 2023-11-13 23:14:19,929 __main__ INFO: Returned Data: None 2023-11-13 23:14:20,009 __main__ INFO: Read[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'933c1fcfa8ed52d2ec05') 2023-11-13 23:14:20,009 __main__ INFO: Write[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'\x03') 2023-11-13 23:14:20,089 __main__ INFO: Returned Data: None 2023-11-13 23:14:20,168 __main__ INFO: Read[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'933c1fcfa8ed52d2ec05') 2023-11-13 23:14:20,168 __main__ INFO: Write[0000ff0a-0000-1000-8000-00805f9b34fb]: bytearray(b'\x04') 2023-11-13 23:14:20,249 __main__ INFO: Returned Data: None

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "933c1fcfa8ed52d2ec05" 2023-11-13 23:19:52,034 __main__ INFO: Connected: True 2023-11-13 23:19:52,412 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-13 23:19:52,412 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'933c1fcfa8ed52d2ec05' 2023-11-13 23:19:52,492 __main__ INFO: Returned Data: None

Link to this headingFlag 10

Modified read Script

import asyncio, string, platform, sys, argparse, logging from bleak import BleakClient from bleak.uuids import normalize_uuid_16, uuid16_dict logger = logging.getLogger(__name__) async def flag(args: argparse.Namespace): async with BleakClient(args.device, winrt=dict(use_cached_services=True)) as client: logger.info(f"Connected: {client.is_connected}") for i in range(1000): #Read UUID or handle read_data = await client.read_gatt_char(args.service) logger.info(f"Read[{args.service}]: {read_data}") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--macos-use-bdaddr", action="store_true", help="when true use Bluetooth address instead of UUID on macOS", ) parser.add_argument( "--device", required=True, help="Which Device MAC to connect to", ) parser.add_argument( "--service", required=True, help="UUID or Handle to write to", ) parser.add_argument( "--data", required=True, help="the Data to write. Can be 0x02, or \"test\"", ) parser.add_argument( "-v", dest="debug", #default=True, action="store_true", help="sets the logging level to debug", ) args = parser.parse_args() #Convert to bytes if args.data.startswith("0x") and all(c in string.hexdigits for c in args.data): args.data = int(args.data, 16) else: args.data = args.data.encode() log_level = logging.DEBUG if args.debug else logging.INFO logging.basicConfig( level=log_level, format="%(asctime)-15s %(name)-8s %(levelname)s: %(message)s", ) asyncio.run(flag(args))

Run the script:

>>> python solve10.py --device "64:E8:33:82:AF:6A" --service 0000ff0b-0000-1000-8000-00805f9b34fb --data a [...] 2023-11-13 23:35:08,025 __main__ INFO: Read[0000ff0b-0000-1000-8000-00805f9b34fb]: bytearray(b'6ffcd214ffebdc0d069e') 2023-11-13 23:35:08,105 __main__ INFO: Read[0000ff0b-0000-1000-8000-00805f9b34fb]: bytearray(b'6ffcd214ffebdc0d069e')

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "933c1fcfa8ed52d2ec05" 2023-11-13 23:19:52,034 __main__ INFO: Connected: True 2023-11-13 23:19:52,412 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-13 23:19:52,412 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'933c1fcfa8ed52d2ec05' 2023-11-13 23:19:52,492 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-13 23:37:37,829 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:10/20')

Link to this headingFlag 11

Modified notification Script

import argparse import asyncio import logging from bleak import BleakClient, BleakScanner from bleak.backends.characteristic import BleakGATTCharacteristic logger = logging.getLogger(__name__) def notification_handler(characteristic: BleakGATTCharacteristic, data: bytearray): """Simple notification handler which prints the data received.""" logger.info(f"{characteristic.description}: {data}") async def main(args: argparse.Namespace): logger.info("starting scan...") if args.address: device = await BleakScanner.find_device_by_address( args.address, cb=dict(use_bdaddr=args.macos_use_bdaddr) ) if device is None: logger.error("could not find device with address '%s'", args.address) return else: device = await BleakScanner.find_device_by_name( args.name, cb=dict(use_bdaddr=args.macos_use_bdaddr) ) if device is None: logger.error("could not find device with name '%s'", args.name) return logger.info("connecting to device...") async with BleakClient(device) as client: logger.info("Connected") await client.start_notify(args.characteristic, notification_handler) read_data = await client.read_gatt_char(args.characteristic) logger.info(f"Read[{args.characteristic}]: {read_data}") read_data = await client.write_gatt_char(args.characteristic, bytearray([0x01]), response=True) logger.info(f"Write[{args.characteristic}]: 0x01 {read_data}") await asyncio.sleep(20.0) await client.stop_notify(args.characteristic) if __name__ == "__main__": parser = argparse.ArgumentParser() device_group = parser.add_mutually_exclusive_group(required=True) device_group.add_argument( "--name", metavar="<name>", help="the name of the bluetooth device to connect to", ) device_group.add_argument( "--address", metavar="<address>", help="the address of the bluetooth device to connect to", ) parser.add_argument( "--macos-use-bdaddr", action="store_true", help="when true use Bluetooth address instead of UUID on macOS", ) parser.add_argument( "characteristic", metavar="<notify uuid>", help="UUID of a characteristic that supports notifications", ) parser.add_argument( "-d", "--debug", action="store_true", help="sets the log level to debug", ) args = parser.parse_args() log_level = logging.DEBUG if args.debug else logging.INFO logging.basicConfig( level=log_level, format="%(asctime)-15s %(name)-8s %(levelname)s: %(message)s", ) asyncio.run(main(args))

Run the script:

>>> python enable_notifications.py --address "64:E8:33:82:AF:6A" 0000ff0c-0000-1000-8000-00805f9b34fb 2023-11-14 00:01:32,679 __main__ INFO: starting scan... 2023-11-14 00:01:32,824 __main__ INFO: connecting to device... 2023-11-14 00:01:34,198 __main__ INFO: Connected 2023-11-14 00:01:34,765 __main__ INFO: Vendor specific: bytearray(b'Listen to me for a single notification') 2023-11-14 00:01:34,765 __main__ INFO: Read[0000ff0c-0000-1000-8000-00805f9b34fb]: bytearray(b'Listen to me for a single notification') 2023-11-14 00:01:34,848 __main__ INFO: Write[0000ff0c-0000-1000-8000-00805f9b34fb]: 0x01 None 2023-11-14 00:01:34,849 __main__ INFO: Vendor specific: bytearray(b'5ec3772bcd00cf06d8eb')

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "5ec3772bcd00cf06d8eb" 2023-11-14 00:04:41,191 __main__ INFO: Connected: True 2023-11-14 00:04:41,608 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-14 00:04:41,609 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'5ec3772bcd00cf06d8eb' 2023-11-14 00:04:41,688 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-14 00:04:54,249 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:11/20')

Link to this headingFlag 12

Listen to handle 0x0044 for a single indication

import argparse import asyncio import logging from bleak import BleakClient, BleakScanner from bleak.backends.characteristic import BleakGATTCharacteristic logger = logging.getLogger(__name__) def notification_handler(characteristic: BleakGATTCharacteristic, data: bytearray): """Simple notification handler which prints the data received.""" logger.info(f"{characteristic.description}: {data}") async def main(args: argparse.Namespace): logger.info("starting scan...") if args.address: device = await BleakScanner.find_device_by_address( args.address, cb=dict(use_bdaddr=args.macos_use_bdaddr) ) if device is None: logger.error("could not find device with address '%s'", args.address) return else: device = await BleakScanner.find_device_by_name( args.name, cb=dict(use_bdaddr=args.macos_use_bdaddr) ) if device is None: logger.error("could not find device with name '%s'", args.name) return logger.info("connecting to device...") async with BleakClient(device) as client: logger.info("Connected") await client.start_notify(args.characteristic, notification_handler) read_data = await client.read_gatt_char(args.characteristic) logger.info(f"Read[{args.characteristic}]: {read_data}") read_data = await client.write_gatt_char(args.characteristic, bytearray([0x01]), response=True) logger.info(f"Write[{args.characteristic}]: 0x01 {read_data}") await asyncio.sleep(20.0) await client.stop_notify(args.characteristic) if __name__ == "__main__": parser = argparse.ArgumentParser() device_group = parser.add_mutually_exclusive_group(required=True) device_group.add_argument( "--name", metavar="<name>", help="the name of the bluetooth device to connect to", ) device_group.add_argument( "--address", metavar="<address>", help="the address of the bluetooth device to connect to", ) parser.add_argument( "--macos-use-bdaddr", action="store_true", help="when true use Bluetooth address instead of UUID on macOS", ) parser.add_argument( "characteristic", metavar="<notify uuid>", help="UUID of a characteristic that supports notifications", ) parser.add_argument( "-d", "--debug", action="store_true", help="sets the log level to debug", ) args = parser.parse_args() log_level = logging.DEBUG if args.debug else logging.INFO logging.basicConfig( level=log_level, format="%(asctime)-15s %(name)-8s %(levelname)s: %(message)s", ) asyncio.run(main(args))

Run the script:

>>> python enable_notifications.py --address "64:E8:33:82:AF:6A" 0000ff0e-0000-1000-8000-00805f9b34fb 2023-11-14 00:10:18,764 __main__ INFO: starting scan... 2023-11-14 00:10:18,923 __main__ INFO: connecting to device... 2023-11-14 00:10:20,253 __main__ INFO: Connected 2023-11-14 00:10:20,612 __main__ INFO: Vendor specific: bytearray(b'Listen to handle 0x0044 for a single indication\x00') 2023-11-14 00:10:20,612 __main__ INFO: Read[0000ff0e-0000-1000-8000-00805f9b34fb]: bytearray(b'Listen to handle 0x0044 for a single indication\x00') 2023-11-14 00:10:20,695 __main__ INFO: Write[0000ff0e-0000-1000-8000-00805f9b34fb]: 0x01 None 2023-11-14 00:10:20,695 __main__ INFO: Vendor specific: bytearray(b'c7b86dd121848c77c113')

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "c7b86dd121848c77c113" 2023-11-14 00:11:07,529 __main__ INFO: Connected: True 2023-11-14 00:11:07,775 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-14 00:11:07,775 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'c7b86dd121848c77c113' 2023-11-14 00:11:07,855 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-14 00:11:20,576 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:12/20')

Link to this headingFlag 13

Listen for a single indication

Run the script:

>>> python enable_notifications.py --address "64:E8:33:82:AF:6A" 0000ff0f-0000-1000-8000-00805f9b34fb 2023-11-14 00:18:31,246 __main__ INFO: starting scan... 2023-11-14 00:18:31,408 __main__ INFO: connecting to device... 2023-11-14 00:18:32,436 __main__ INFO: Connected 2023-11-14 00:18:32,658 __main__ INFO: Vendor specific: bytearray(b'Listen to me for multi notifications') 2023-11-14 00:18:32,659 __main__ INFO: Read[0000ff0f-0000-1000-8000-00805f9b34fb]: bytearray(b'Listen to me for multi notifications') 2023-11-14 00:18:32,738 __main__ INFO: Write[0000ff0f-0000-1000-8000-00805f9b34fb]: 0x01 None 2023-11-14 00:18:32,738 __main__ INFO: Vendor specific: bytearray(b'U no want this msg\x00\x00') 2023-11-14 00:18:33,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:34,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:35,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:36,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:37,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:38,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:39,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:40,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:41,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:42,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:43,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:44,739 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:45,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:46,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:47,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:48,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:49,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:50,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:51,741 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd') 2023-11-14 00:18:52,738 __main__ INFO: Vendor specific: bytearray(b'c9457de5fd8cafe349fd')

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "c9457de5fd8cafe349fd" 2023-11-14 00:19:15,739 __main__ INFO: Connected: True 2023-11-14 00:19:15,978 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-14 00:19:15,979 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'c9457de5fd8cafe349fd' 2023-11-14 00:19:16,058 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-14 00:19:31,739 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:13/20')

Link to this headingFlag 14

Listen to handle 0x004a for multi indications

Run the script:

>>> python enable_notifications.py --address "64:E8:33:82:AF:6A" 0000ff11-0000-1000-8000-00805f9b34fb 2023-11-14 00:20:20,240 __main__ INFO: starting scan... 2023-11-14 00:20:20,390 __main__ INFO: connecting to device... 2023-11-14 00:20:21,743 __main__ INFO: Connected 2023-11-14 00:20:22,141 __main__ INFO: Vendor specific: bytearray(b'Listen to handle 0x004a for multi indications\x00') 2023-11-14 00:20:22,142 __main__ INFO: Read[0000ff11-0000-1000-8000-00805f9b34fb]: bytearray(b'Listen to handle 0x004a for multi indications\x00') 2023-11-14 00:20:22,218 __main__ INFO: Write[0000ff11-0000-1000-8000-00805f9b34fb]: 0x01 None 2023-11-14 00:20:22,219 __main__ INFO: Vendor specific: bytearray(b'U no want this msg\x00\x00') 2023-11-14 00:20:22,302 __main__ INFO: Vendor specific: bytearray(b'b6f3a47f207d38e16ffa') 2023-11-14 00:20:22,378 __main__ INFO: Vendor specific: bytearray(b'b6f3a47f207d38e16ffa') 2023-11-14 00:20:22,458 __main__ INFO: Vendor specific: bytearray(b'b6f3a47f207d38e16ffa')

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "b6f3a47f207d38e16ffa" 2023-11-14 00:21:05,699 __main__ INFO: Connected: True 2023-11-14 00:21:05,938 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-14 00:21:05,939 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'b6f3a47f207d38e16ffa' 2023-11-14 00:21:06,021 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-14 00:21:15,783 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:14/20')

Link to this headingFlag 15

Connect with BT MAC address 11:22:33:44:55:66’

TODO

Link to this headingFlag 16

Set your connection MTU to 444

Needed a separate library for MTU Support bluepy

Script:

#!/usr/bin/env python3 import bluepy.btle as btle dev = btle.Peripheral('64:E8:33:82:AF:6A') dev.setMTU(444) print(dev.readCharacteristic(0x4e).decode())

Run the script:

>>> python mtu.py b1e409e5a4eaf9fe5158

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "b1e409e5a4eaf9fe5158" 2023-11-22 15:05:33,163 __main__ INFO: Connected: True 2023-11-22 15:05:33,537 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-22 15:05:33,537 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'b1e409e5a4eaf9fe5158' 2023-11-22 15:05:33,617 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-22 15:08:29,981 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:15/20')

Link to this headingFlag 17

Write+resp ‘hello’

Write the String:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff14-0000-1000-8000-00805f9b34fb --data "hello" 2023-11-22 15:11:26,263 __main__ INFO: Connected: True 2023-11-22 15:11:26,621 __main__ INFO: Read[0000ff14-0000-1000-8000-00805f9b34fb]: bytearray(b"Write+resp \'hello\' ") 2023-11-22 15:11:26,621 __main__ INFO: Write[0000ff14-0000-1000-8000-00805f9b34fb]: b'hello' 2023-11-22 15:11:26,700 __main__ INFO: Returned Data: None

Read the flag:

>>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep 0000ff14-0000-1000-8000-00805f9b34fb 2023-11-22 15:12:19,182 __main__ INFO: [Characteristic] 0000ff14-0000-1000-8000-00805f9b34fb (Handle: 79): Vendor specific (read,write), Value: bytearray(b'd41d8cd98f00b204e980\x00')

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "d41d8cd98f00b204e980" 2023-11-22 15:14:09,430 __main__ INFO: Connected: True 2023-11-22 15:14:09,824 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-22 15:14:09,824 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'd41d8cd98f00b204e980' 2023-11-22 15:14:09,904 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-22 15:14:33,105 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:16/20')

Link to this headingFlag 18

‘No notifications here! really?’
Read Notification:

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "b1e409e5a4eaf9fe5158" 2023-11-22 15:05:33,163 __main__ INFO: Connected: True 2023-11-22 15:05:33,537 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-22 15:05:33,537 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'b1e409e5a4eaf9fe5158' 2023-11-22 15:05:33,617 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-22 15:08:29,981 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:15/20')

Link to this headingFlag 19

‘So many properties!’

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "b1e409e5a4eaf9fe5158" 2023-11-22 15:05:33,163 __main__ INFO: Connected: True 2023-11-22 15:05:33,537 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-22 15:05:33,537 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'b1e409e5a4eaf9fe5158' 2023-11-22 15:05:33,617 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-22 15:08:29,981 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:15/20')

Link to this headingFlag 20

“md5 of author’s twitter handle”

Write the flag:

>>> python write_data.py --device "64:E8:33:82:AF:6A" --service 0000ff02-0000-1000-8000-00805f9b34fb --data "b1e409e5a4eaf9fe5158" 2023-11-22 15:05:33,163 __main__ INFO: Connected: True 2023-11-22 15:05:33,537 __main__ INFO: Read[0000ff02-0000-1000-8000-00805f9b34fb]: bytearray(b'Write Flags Here') 2023-11-22 15:05:33,537 __main__ INFO: Write[0000ff02-0000-1000-8000-00805f9b34fb]: b'b1e409e5a4eaf9fe5158' 2023-11-22 15:05:33,617 __main__ INFO: Returned Data: None >>> python service_explorer.py --address "64:E8:33:82:AF:6A" 2>&1 | grep Score 2023-11-22 15:08:29,981 __main__ INFO: [Characteristic] 0000ff01-0000-1000-8000-00805f9b34fb (Handle: 41): Vendor specific (read), Value: bytearray(b'Score:15/20')